/**
 * 混入方法
 */
import React from 'react';
import _ from 'lodash';
import { StateType } from '@/common-typings';
import { ConnectProps } from '@/models/connect';
import { TableConfigProps } from '@/components/CreateTable';
import { FormConfigProps } from '@/components/CreateForm';
import { getFormatDate, initDefaultDate, initDefaultDateByMonths, types } from '@/utils/utils';
import { assignDefaultFormData } from '@/components/Common/utils';
import { filterFormData } from './utils';

interface MixinConnectProps extends StateType, ConnectProps {}

class Mixins extends React.PureComponent<MixinConnectProps, StateType> {
  public bindFormRef: any;

  public bindTableRef: any;

  // 储存最初默认form的数据
  public defaultFormParams: any = {};

  // 储存上一次form的数据
  public prevFormParams: any = {};

  // 默认分页信息
  public defaultPagination = {
    page: 1,
    size: 20,
    total: 0,
  };

  public formConfig: FormConfigProps = {
    config: [],
  };

  public tableConfig: TableConfigProps = {
    data: [],
    header: [],
  };

  // 初始化页面日期数据
  initDefaultDate = initDefaultDate;

  // 初始化页面日期数据，从月初计算
  initDefaultDateByMonths = initDefaultDateByMonths;

  // 日期转换器具
  getFormatDate = getFormatDate;

  // 获取表单默认数据
  assignDefaultFormData = assignDefaultFormData;

  // 过滤表单的数据
  filterFormData = filterFormData;

  /**
   * 更新配置的key值
   * @param list
   */
  filtersLabelToText = (list: any[]) => {
    if (types(list) === 'array') {
      list.forEach((item: any) => {
        item.text = item.label;
      });
    }
    return list;
  };

  /**
   * 更新状态
   * @param data
   * @param cb
   */
  changeState = (data: StateType, cb?: Function) => {
    if (types(data) === 'object') {
      this.setState(
        preState => ({
          ...preState,
          ...data,
        }),
        () => {
          if (cb) cb();
        },
      );
    }
  };

  /**
   * 切换loading
   * @param loading
   * @param includeTableLoading
   */
  changePageLoading = (loading: StateType) => {
    this.changeState(loading);
  };

  /**
   * 更新分页
   * @param param
   * @param cb
   */
  updatePagination = (param: StateType, fn?: Function) => {
    if (param) {
      this.getFormData().then(res => {
        // 分页数据
        const pagination = {
          page: param.pageNum,
          size: param.pageSize,
          total: param.total,
        };

        let newState = {
          pagination,
        };

        const { tableFilters } = this.state;
        // 判断是否有filters参数
        if (param.hasOwnProperty('filters') && tableFilters) {
          newState = Object.assign({}, newState, {
            tableFilters: {
              ...tableFilters,
              ...param.filters,
            },
          });
        }

        this.changeState(newState, () => {
          if (fn) {
            fn(res);
          }
        });
      });
    }
  };

  /**
   * 获取表单数据
   * 建议表单绑定ref，同步数据才无bug
   * @param refName
   */
  getFormData = (refName = 'bindFormRef') =>
    new Promise((resolve, reject) => {
      // 当绑定页面绑定有ref时，先通过表单的校验
      if (this[refName]) {
        this[refName].validateFields((error: any, value: {}) => {
          if (!error) {
            const { formConfig } = this[refName].props;
            this.filterFormData(value, formConfig);

            // 组合默认值以及表单校验通过的值
            resolve({ ...this.defaultFormParams, ...value });
          }
        });

        // 如果没有绑定表单时
      } else {
        const newParam = _.isEmpty(this.prevFormParams)
          ? this.defaultFormParams
          : this.prevFormParams;
        resolve(newParam);
      }
    });

  /**
   * 更新table的数据
   * @param param
   * @param fn
   */
  updateTableData = (param: StateType, fn?: Function) => {
    if (param) {
      const data: StateType = {
        pagination: {
          page: param.pageNum,
          size: param.pageSize !== 0 ? param.pageSize : this.defaultPagination.size,
          total: param.total,
        },
      };

      // 如果有列表数据
      if (param.keywords) {
        data.list = param[param.keywords] || [];
      } else if (param.hasOwnProperty('list')) {
        data.list = param.list || [];
      }

      this.changeState(data, () => {
        if (fn) fn();
      });
    }
  };

  /**
   * 获取分页数据
   */
  getPaginationData = () => {
    const { pagination } = this.state;
    if (pagination) {
      return { page: pagination.page, size: pagination.size };
    }
    return {};
  };

  /**
   * 初始化form的参数，获取form表单中当默认值
   * @param params
   */
  initDefaultFormParams = (props: StateType) => {
    if (_.isEmpty(this.defaultFormParams)) {
      this.defaultFormParams = {
        ...this.defaultFormParams,
        ...this.assignDefaultFormData(props),
      };
    }
  };

  getTableFiltersData = () => {
    const { tableFilters } = this.state;
    const result = {};
    if (tableFilters && types(tableFilters) === 'object') {
      Object.keys(tableFilters).forEach(key => {
        if (tableFilters[key].length) {
          if (tableFilters[key].length === 1) {
            const [data] = tableFilters[key];
            result[key] = data;
          } else {
            result[key] = tableFilters[key].join(',');
          }
        }
      });
    }
    return result;
  };

  /**
   * 初始化请求参数, 与产品确认了需求，form内参数变化都从第一页开始查询，pagination变化时从变化页开始查询
   * @param param
   */
  initRequestData = (param = {}, key?: string) => {
    const paginationParam = this.getPaginationData();
    const tableFilterData = this.getTableFiltersData();
    let result: StateType = {
      ...paginationParam,
      ...tableFilterData,
    };

    /**
     * 当未传递参数时
     * 该情况为第一次初始化请求的状况
     */
    if (_.isEmpty(param)) {
      const newParam = _.isEmpty(this.prevFormParams)
        ? this.defaultFormParams
        : this.prevFormParams;
      result = { ...result, ...newParam };
    }

    /**
     * 如果有key，则代表从from表单传递过来的数据
     */
    if (key) {
      // 储存上一次表单变动的值
      this.prevFormParams = Object.assign({}, param);
      // param参数都来自于form, 从第一页开始查询数据
      result = { ...result, ...param, page: 1 };
    }

    /**
     * 没有key，则代表从table变化传递过来的参数
     */
    result = { ...result, ...param };
    return result;
  };
}

export default Mixins;
